package internal

import (
	"fmt"
	"log"
	"os/exec"
	"strings"

	"github.com/AlecAivazis/survey/v2"
	"github.com/spf13/cobra"
	"nodemessage.com/ruov-cli/rlog"
)

var (
	gitLogFlag = false
)

// gitCmd represents the git command
var gitCmd = &cobra.Command{
	Use:     "git",
	Short:   "git推送操作",
	Long:    "规范项目的提交流程，提供便捷的 git 操作，推送到当前远程分支",
	Example: "ruov git <file1> <file2> ...\n提交当前目录: ruov git .",
	PreRun: func(cmd *cobra.Command, args []string) {

	},
	Run: func(cmd *cobra.Command, args []string) {
		if gitLogFlag {
			_, err := gitLog()
			if err != nil {
				rlog.Logger.Fatal("查看日志失败: %v", err)
			}
			return
		}
		if len(args) == 0 {
			cmd.Help()
			return
		}
		message := commitMessage()
		rlog.Logger.Info("[add]添加文件到暂存区: %s", strings.Join(args, ","))
		err := gitAdd(args)
		if err != nil {
			rlog.Logger.Fatal("添加文件到暂存区失败: %v", err)
		}
		rlog.Logger.Info("[add]添加文件到暂存区成功")
		rlog.Logger.Info("[commit]提交更改")
		err = gitCommit(message)
		if err != nil {
			rlog.Logger.Fatal("[commit]提交更改失败: %v", err)
		}
		rlog.Logger.Info("[commit]提交更改成功")
		rlog.Logger.Info("[push]推送中...")
		err = gitPush()
		if err != nil {
			rlog.Logger.Fatal("[push]推送失败: %v", err)
		}
		rlog.Logger.Info("[push]推送成功")
	},
}

func init() {
	gitCmd.Flags().BoolVar(&gitLogFlag, "log", false, "查看日志")
}

// runCommand 执行给定的命令并返回输出
func runGitCommand(echo bool, args ...string) (string, error) {
	cmd := exec.Command("git", args...)
	output, err := cmd.CombinedOutput()
	if echo {
		rlog.Logger.Info("\n\n------>\n" + string(output) + "<------\n")
	}
	return string(output), err
}

// gitAdd 添加文件到 Git 暂存区
func gitAdd(files []string) error {
	_, err := runGitCommand(true, append([]string{"add"}, files...)...)
	return err
}

// commitMessage 编写提交信息
func commitMessage() string {
	commitTypes := []string{
		"refactor: 既不修复bug也不添加新功能的代码更改",
		"feat:     新功能",
		"fix:      修复bug",
		"docs:     仅文档更改",
		"style:    不影响代码含义的更改（空格、格式、缺少分号等）",
		"perf:     提高性能的代码更改",
		"test:     添加缺失的测试或修正现有测试",
		"chore:    对构建过程或辅助工具和库的更改，例如文档生成",
	}
	questions := []*survey.Question{
		{
			Name: "type",
			Prompt: &survey.Select{
				Message:  "选择您要提交的更改类型（可选）:",
				Options:  commitTypes,
				PageSize: 10,
			},
		},
		{
			Name: "body",
			Prompt: &survey.Input{
				Message: "输入详细描述（必选）:",
			},
			Validate: survey.ComposeValidators(survey.Required),
		},
		{
			Name: "subject",
			Prompt: &survey.Input{
				Message: "输入简洁概述,用来概括本次提交（最大20个字符 必选）:",
			},
			Validate: survey.ComposeValidators(survey.Required, survey.MaxLength(20)),
		},
		{
			Name: "issues",
			Prompt: &survey.Input{
				Message: "输入任何相关问题（例如 'fixes #123'，可选）:",
			},
		},
	}
	answers := struct {
		Type    string
		Subject string
		Body    string
		Issues  string
	}{}
	err := survey.Ask(questions, &answers)
	if err != nil {
		log.Fatalf("Failed to collect input: %v", err)
	}
	if answers.Subject == "" {
		answers.Subject = "提交修改"
	}
	typeMsg := strings.Split(answers.Type, ":")
	commitMessage := fmt.Sprintf("%s\n\n%s", typeMsg[0]+": "+answers.Subject, answers.Body)
	if answers.Issues != "" {
		commitMessage += fmt.Sprintf("\n\n%s", answers.Issues)
	}
	if err != nil {
		rlog.Logger.Fatal("提交信息填写异常:%v", err)
	}
	return commitMessage
}

// gitCommit 提交更改
func gitCommit(msg string) error {
	_, err := runGitCommand(true, "commit", "-m", msg)
	return err
}

// gitPush 推送到当前分支
func gitPush() error {
	// 获取当前分支名称
	output, err := runGitCommand(true, "rev-parse", "--abbrev-ref", "HEAD")
	if err != nil {
		return err
	}

	branch := strings.TrimSpace(output) // 当前分支名称

	// 推送到当前分支
	_, err = runGitCommand(true, "push", "origin", branch)
	return err
}

// gitLog 显示提交日志
func gitLog() (string, error) {
	return runGitCommand(true, "log", "--oneline")
}
